
package com.hlkj.pay.task;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import cn.hutool.core.bean.BeanUtil;
import com.hlkj.framework.common.util.collection.CollectionUtils;
import com.hlkj.pay.dto.merchant.MerchantInfoQueryDto;
import com.hlkj.pay.dto.payment.MerchantPaymentPageQueryDto;
import com.hlkj.pay.dto.payment.MerchantPaymentStatisticsDto;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.infrastructure.model.merchant.MerchantInfoDO;
import com.hlkj.pay.infrastructure.model.payment.MerchantPaymentStatisticsDO;
import com.hlkj.pay.service.merchant.IMerchantService;
import com.hlkj.pay.service.payment.IMerchantPaymentService;
import com.hlkj.pay.service.payment.IMerchantPaymentStatisticsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;

/**
 * 代付统计
 * @author HlpayTeam
 * @date 2024/10/29 10:43
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class MerchantPaymentTasks {

    private final IMerchantPaymentService merchantPaymentService;

    private final IMerchantPaymentStatisticsService paymentStatisticsService;

    private final IMerchantService merchantService;

    @Value("${server.port:8020}")
    private String serverPort;

    @Value("${hlkj.task.port:8020}")
    private String taskPort;

    // 2点进行统计
    @Scheduled(cron = "0 40 2 * * *")
    public void cronTask() {
        if (!serverPort.equals(taskPort)) {
            log.info("当前task port 非目标port serverPort:{},taskPort:{}", serverPort, taskPort);
            return;
        }
        processStatistics(null);
    }


    public void processStatistics(String startDate, String endDate) {
        if (!StringUtils.hasText(startDate)) {
            return;
        }
        if (!StringUtils.hasText(endDate)) {
            processStatistics(startDate);
            return;
        }
        LocalDate startLocalDate = LocalDate.parse(startDate);
        LocalDate endLocalDate = LocalDate.parse(endDate);
        // 计算天数差
        long daysBetween = ChronoUnit.DAYS.between(startLocalDate, endLocalDate);
        for (int i = 0; i < daysBetween; i++) {
            processStatistics(startLocalDate.plusDays(i).toString());
        }
    }

    @Transactional
    private void processStatistics(String date) {
        log.info("处理代付统计的日期为:{}",date);
        // 统计昨天的数据
        LocalDate localDate = LocalDate.now().plusDays(-1);
        if (StringUtils.hasText(date)) {
            localDate = LocalDate.parse(date);
        }
        long startQueryTime = LocalDateTime.of(localDate.getYear(), localDate.getMonth(), localDate.getDayOfMonth(), 0, 0, 0).atZone(ZoneId.of("Asia/Shanghai")).toInstant()
                .toEpochMilli();
        long endQueryTime = LocalDateTime.of(localDate.getYear(), localDate.getMonth(), localDate.getDayOfMonth(), 23, 59, 59).atZone(ZoneId.of("Asia/Shanghai")).toInstant()
                .toEpochMilli();

        try {
            MerchantInfoQueryDto merchantInfoQueryDto = new MerchantInfoQueryDto();
            merchantInfoQueryDto.setSnType(MerchantEnum.MERCHANT_SN_TYPE.MERCHANT.getCode());
            List<MerchantInfoDO> merchantInfoDOList = merchantService.queryList(merchantInfoQueryDto);
            for (MerchantInfoDO merchantInfoDO : merchantInfoDOList) {
                List<MerchantPaymentStatisticsDO> addStatisticsList = new ArrayList<>();
                //统计维度 1 商户维度 2 支付方式 3 APPID 4 通道编码
                // 商户维度
                MerchantPaymentPageQueryDto merchantPaymentPageQueryDto = new MerchantPaymentPageQueryDto();
                merchantPaymentPageQueryDto.setStartQueryTime(startQueryTime);
                merchantPaymentPageQueryDto.setEndQueryTime(endQueryTime);
                merchantPaymentPageQueryDto.setSn(merchantInfoDO.getSn());
                List<MerchantPaymentStatisticsDto> snList = merchantPaymentService.statistics(merchantPaymentPageQueryDto, "p.sn");

                boolean check = true;
                String remark = null;
                List<MerchantPaymentStatisticsDO> statisticsList = paymentStatisticsService.queryList(1, merchantInfoDO.getSn(), startQueryTime);
                if (!CollectionUtils.isEmpty(statisticsList)) {
                    MerchantPaymentStatisticsDO orderStatisticsDO = statisticsList.get(0);
                    MerchantPaymentStatisticsDto statisticsDto = snList.get(0);
                    if (!orderStatisticsDO.getSubmitOrderCount().equals(statisticsDto.getSubmitOrderCount()) || !orderStatisticsDO.getRefundCount().equals(statisticsDto.getRefundCount())
                            || !orderStatisticsDO.getPayOrderCount().equals(statisticsDto.getPayOrderCount())) {
                        log.info("原统计数据与实际查询订单、退款数据不匹配 统计提交订单数量:submitOrderCount:{},统计支付订单数量:submitOrderCount:{},统计退款订单数量:submitOrderCount:{}", orderStatisticsDO.getSubmitOrderCount(),
                                orderStatisticsDO.getPayOrderCount(), orderStatisticsDO.getRefundCount());
                        log.info("原统计数据与实际查询订单、退款数据不匹配 实际提交订单数量:submitOrderCount:{},实际支付订单数量:submitOrderCount:{},实际退款订单数量:submitOrderCount:{}", statisticsDto.getSubmitOrderCount(), statisticsDto.getPayOrderCount(),
                                statisticsDto.getRefundCount());
                        remark = "统计错误 需要重算 统计提交订单数量:" + orderStatisticsDO.getSubmitOrderCount() + ",统计支付订单数量:" + orderStatisticsDO.getPayOrderCount() + ",统计退款订单数量:"
                                + orderStatisticsDO.getRefundCount();
                        remark = remark + ";实际订单数量:" + statisticsDto.getSubmitOrderCount() + ",统计支付订单数量:" + statisticsDto.getPayOrderCount() + ",统计退款订单数量:" + statisticsDto.getRefundCount();
                        check = false;
                    }
                    else {
                        log.info("原统计数据与实际查询订单、退款数据匹配 统计提交订单数量:submitOrderCount:{},统计支付订单数量:submitOrderCount:{},统计退款订单数量:submitOrderCount:{}", orderStatisticsDO.getSubmitOrderCount(),
                                orderStatisticsDO.getPayOrderCount(), orderStatisticsDO.getRefundCount());
                        log.info("原统计数据与实际查询订单、退款数据匹配 实际提交订单数量:submitOrderCount:{},实际支付订单数量:submitOrderCount:{},实际退款订单数量:submitOrderCount:{}",  statisticsDto.getSubmitOrderCount(), statisticsDto.getPayOrderCount(),
                                statisticsDto.getRefundCount());
                    }
                }

                if (check && !CollectionUtils.isEmpty(statisticsList)) {
                    continue;
                }

                if (!CollectionUtils.isEmpty(statisticsList)) {
                    paymentStatisticsService.deleteByTime(startQueryTime, merchantInfoDO.getSn(), remark);
                }

                snList.stream().forEach(obj -> {
                    MerchantPaymentStatisticsDO paymentStatisticsDO = BeanUtil.copyProperties(obj, MerchantPaymentStatisticsDO.class);
                    paymentStatisticsDO.setType(1);
                    paymentStatisticsDO.setRelationId(obj.getSn());
                    paymentStatisticsDO.setTime(startQueryTime);
                    addStatisticsList.add(paymentStatisticsDO);
                });

//                // 类型 0 代付 1 充值
                List<MerchantPaymentStatisticsDto> payList = merchantPaymentService.statistics(merchantPaymentPageQueryDto, "p.sn,p.payment_type");
                payList.stream().forEach(obj -> {
                    MerchantPaymentStatisticsDO paymentStatisticsDO = BeanUtil.copyProperties(obj, MerchantPaymentStatisticsDO.class);
                    paymentStatisticsDO.setType(2);
                    paymentStatisticsDO.setRelationId(obj.getPaymentType());
                    paymentStatisticsDO.setTime(startQueryTime);
                    addStatisticsList.add(paymentStatisticsDO);
                });

                // app_id
                List<MerchantPaymentStatisticsDto> appList = merchantPaymentService.statistics(merchantPaymentPageQueryDto, "p.sn,p.app_id");
                appList.stream().forEach(obj -> {
                    MerchantPaymentStatisticsDO paymentStatisticsDO = BeanUtil.copyProperties(obj, MerchantPaymentStatisticsDO.class);
                    paymentStatisticsDO.setType(3);
                    paymentStatisticsDO.setRelationId(obj.getAppId());
                    paymentStatisticsDO.setTime(startQueryTime);
                    addStatisticsList.add(paymentStatisticsDO);
                });

                // 子通道编码
                List<MerchantPaymentStatisticsDto> channelList = merchantPaymentService.statistics(merchantPaymentPageQueryDto, "p.sn,p.mch_channel_code");
                channelList.stream().forEach(obj -> {
                    MerchantPaymentStatisticsDO paymentStatisticsDO = BeanUtil.copyProperties(obj, MerchantPaymentStatisticsDO.class);
                    paymentStatisticsDO.setType(4);
                    paymentStatisticsDO.setRelationId(obj.getMchChannelCode());
                    paymentStatisticsDO.setTime(startQueryTime);
                    addStatisticsList.add(paymentStatisticsDO);
                });

                paymentStatisticsService.addPaymentList(addStatisticsList);

            }
        } catch (Exception e) {
            log.error("处理代付统计异常", e);
        }
    }

}
